/**
 * 
 */
package com.googlecode.pcapj;

import java.io.File;
import java.io.IOException;

import org.bridj.Pointer;

import com.googlecode.pcapj.bridj.Wpcap;
import com.googlecode.pcapj.bridj.pcap_pkthdr;

/**
 * 
 */
class DumpFileWriterImpl implements DumpFileWriter{
	private PcapWrapper pcapWrapper;
	private CapturedFactory capturedFactory;
//	private File file;
	private Pointer<Byte> fileName;
	private Pointer<?> dumpFilePointer;
	
	/**
	 * @param pointer
	 * @throws IOException 
	 */
	DumpFileWriterImpl(PcapWrapper pcapWrapper, CapturedFactory capturedFactory, File file) throws IOException {
		super();
		this.pcapWrapper = pcapWrapper;
		this.capturedFactory = capturedFactory;
//		this.file = file;
		this.fileName = Pointer.pointerToCString(file.getPath());
		this.dumpFilePointer = pcapWrapper.openDumpFile(fileName);
	}
	private void requireOpened() throws IOException{
		if(isClosed()){
			throw new IOException("Dump file is not opened.");
		}
	}
	private boolean isClosed(){
		return dumpFilePointer == Pointer.NULL;
	}
	/* (non-Javadoc)
	 * @see java.io.Closeable#close()
	 */
	public void close() throws IOException {
		if(fileName != Pointer.NULL){
			fileName.release();
			
			@SuppressWarnings("unchecked")
			Pointer<Byte> null1 = Pointer.NULL;
			fileName = null1;
		}
		if(dumpFilePointer != Pointer.NULL){
			Wpcap.pcap_dump_close(dumpFilePointer);
			dumpFilePointer = Pointer.NULL;
		}
	}

	/* (non-Javadoc)
	 * @see com.googlecode.pcapj.DumpFileWriter#loop(com.googlecode.pcapj.DumpFilter)
	 */
	public boolean loop(final DumpFilter dumpFilter) throws IOException {
		requireOpened();
		Wpcap.packet_handler packet_handler = new Wpcap.packet_handler() {
			@Override
			public void handle(Pointer<Byte> param, Pointer<pcap_pkthdr> header, Pointer<Byte> pkt_data) {
				try {
					Captured captured = capturedFactory.newCaptured(pcapWrapper.getDatalink() , header, pkt_data);
					if(!dumpFilter.filter(captured)){
						pcapWrapper.writeDumpFile(dumpFilePointer, header, pkt_data);
					}
					
				} catch (IOException e) {
					throw new PcapJRuntimeException(e);
				}
			}
		};
		return pcapWrapper.loop(packet_handler, 0, fileName);
	}

	/* (non-Javadoc)
	 * @see com.googlecode.pcapj.DumpFileWriter#read()
	 */
	public CapturedWriter read() throws PcapJTimeoutException, IOException {
		requireOpened();
    	Pointer<Pointer<pcap_pkthdr>> pHeader = Pointer.allocatePointer(pcap_pkthdr.class);
    	Pointer<Pointer<Byte>> pData = Pointer.allocatePointer(Byte.class);
    	
		Captured captured = null;
		if(!pcapWrapper.read(pHeader, pData)){
			captured = capturedFactory.newCaptured(pcapWrapper.getDatalink(), pHeader.get(), pData.get());
		}
		return new CapturedWriterImpl(pcapWrapper, captured, dumpFilePointer, pHeader, pData);
	}

	/* (non-Javadoc)
	 * @see com.googlecode.pcapj.DumpFileWriter#breakLoop()
	 */
	public void breakLoop() throws IOException {
		requireOpened();
		pcapWrapper.breakLoop();
	}
	
}
